import traceback
import os
import sys
import pandas as pd
from openpyxl import load_workbook
from AnalyticsFunctionCoder import AnalyticsFunctionCoder
from AnalyticsParamsCoder import AnalyticsParamsCoder


class AnalyticsCoder:

    # const parms
    SOURCE_FILE_NAME = '../../Iteration/VersionHolder/Excels/Analytics/Analytics.xlsx'
    SHEET_NAME = '#事件数据'
    HEAD_EVENT_TAG = '事件标签'
    HEAD_EVENT_NAME = '事件名（必填）'
    HEAD_FIELD_TAG = '属性名（必填）'
    HEAD_FIELD_TYPE = '属性类型（必填）'
    HEAD_FIELD_EXPLAIN = '属性说明'
    CLIENT_FIELD_NAME = 'client'


    # construction
    def __init__(self):
        self._funcCoder = AnalyticsFunctionCoder()
        self._paramsCoder = AnalyticsParamsCoder()
        self._funcArr = [] 
        self._paramsArr = [] 
        self._eventNameArr = []

     # 执行生成逻辑
    def PerformGenerateProcess(self, version):
        print(f"### 加载源文件: {self.SOURCE_FILE_NAME}")
        self.LoadSourceFile()
        
        print(f"### 处理合并单元格...")
        self.HandleMergedCells()
        
        print(f"### 处理非合并的单元格...")
        self.HandleNonMergedCells()
        
        print(f"### 执行方法生成与生成AnalyticsMgr.cs脚本!")
        self.PerformFunctionProcess(version)
        
        print(f"### 执行参数生成与生成AnalyticsParams.cs脚本!")
        self.PerformParamsProcess(version)

    
    # 执行生成function文本
    def PerformFunctionProcess(self, version):
        self.GenerateMergedFunctionText(self.merged_rows)
        self.GenerateNonMergedFunctionText(self.non_merged_rows)
        self._funcCoder.SaveAllFuncs(self._funcArr, version)

    # 执行生成参数文本
    def PerformParamsProcess(self, version):
        self.GenerateMergedParamsText(self.merged_rows)
        self.GenerateNonMergedParamsText(self.non_merged_rows)
        self._paramsCoder.GenerateEventDefineText(self._eventNameArr)
        self._paramsCoder.SaveAllParams(self._paramsArr, version)
    
    
    # 加载表格资源
    def LoadSourceFile(self):
        self.df = pd.read_excel(self.SOURCE_FILE_NAME, sheet_name = self.SHEET_NAME)
        self.wb = load_workbook(filename = self.SOURCE_FILE_NAME)
        self.sheet = self.wb[self.SHEET_NAME]


    # 处理合并单元格
    def HandleMergedCells(self):
        # 存放合并单元格的行
        self.merged_rows = []
        # 先获取所有涵盖A列的合并单元格
        merged_cells_A = [mc for mc in self.sheet.merged_cells.ranges if mc.bounds[0] == 1 or mc.bounds[2] == 1]
        # 处理所有的合并单元格
        # 按照起始行排序（行编号从1开始）
        sorted_merged_cells_A = sorted(merged_cells_A, key=lambda x: x.bounds[1])

        for cell_range in sorted_merged_cells_A:
            start_row, end_row = cell_range.bounds[1], cell_range.bounds[3]
            pdBeginIndex = start_row - 2
            pdEndIndex = end_row - 2
            if pdBeginIndex < 0 or pdEndIndex < 0:
                continue
            row_data = self.df.iloc[pdBeginIndex]
            client_tag = row_data[self.HEAD_EVENT_TAG]
            if client_tag == self.CLIENT_FIELD_NAME:
                single_range = [pdBeginIndex, pdEndIndex]
                self.merged_rows.append(single_range)
            #print(f"合并单元格数据： {self.merged_rows}")

        
    # 处理非合并单元格
    def HandleNonMergedCells(self):
        # 处理所有的非合并单元格
        # 存档非合并单元格的行
        self.non_merged_rows = []
        # 准备一个列表来收集非合并的单元格
        merged_cells_ranges = self.sheet.merged_cells.ranges

        for cell in self.sheet['A']:
            if not any(cell.coordinate in merged_cell for merged_cell in merged_cells_ranges):
                pdIndex = cell.row - 2
                if pdIndex < 0:
                    continue
                row_data = self.df.iloc[pdIndex]
                client_tag = row_data[self.HEAD_EVENT_TAG]

                if client_tag == self.CLIENT_FIELD_NAME:
                    self.non_merged_rows.append(pdIndex)
        #print(f"非合并单元格数据： {self.non_merged_rows}")


    # 生成非合并单元格的Func数据
    def GenerateNonMergedFunctionText(self, arr):
        for rowId in arr:
            row_data = self.df.iloc[rowId]
            event_name = row_data[self.HEAD_EVENT_NAME]
            filed_name = row_data[self.HEAD_FIELD_TAG]
            field_type = row_data[self.HEAD_FIELD_TYPE]

            try:
                funcStr = self._funcCoder.GenerateSingleFunction(event_name, [field_type], [filed_name])
                self._funcArr.append(funcStr)
            except Exception as e:
                print(f"[生成调用函数] 处理事件名为{event_name}的非合并单元格时，捕获到异常{e}")


    # 生成合并单元格的Func数据
    def GenerateMergedFunctionText(self, arr):
        for group in arr:
            type_list = []
            name_list = []
            beginRow = group[0]
            endRow = group[1]
            event_name = ''
            for rowId in range(beginRow, endRow + 1):
                row_data = self.df.iloc[rowId]
                if rowId == beginRow:
                    event_name = row_data[self.HEAD_EVENT_NAME]
                field_type = row_data[self.HEAD_FIELD_TYPE]
                field_name = row_data[self.HEAD_FIELD_TAG]
                type_list.append(field_type) 
                name_list.append(field_name)

            try:
                funcStr = self._funcCoder.GenerateSingleFunction(event_name, type_list, name_list)
                self._funcArr.append(funcStr)
            except Exception as e:
                print(f"[生成调用函数] 处理事件名为{event_name}的合并单元格时，捕获到异常{e}")

    # 生成非合并单元格的params数据
    def GenerateNonMergedParamsText(self, arr):
          for rowId in arr:
            row_data = self.df.iloc[rowId]
            event_name = row_data[self.HEAD_EVENT_NAME]
            field_type = row_data[self.HEAD_FIELD_TYPE]
            field_name = row_data[self.HEAD_FIELD_TAG]
            field_explain = row_data[self.HEAD_FIELD_EXPLAIN]
            self._eventNameArr.append(event_name)
            if pd.isna(field_explain) or pd.isna(field_name):
                continue

            try:   
                param_str_list = self._paramsCoder.GenerateSingleParmsClass(event_name, [field_type], [field_name], [field_explain])
                if(len(param_str_list) > 0):
                    self._paramsArr.append(param_str_list[0])
            except Exception as e:
                print(f"[生成参数结构类] 处理事件名为{event_name}的非合并单元格时，捕获到异常{e}")
    

    # 生成合并单元格的params数据
    def GenerateMergedParamsText(self, arr):
        for group in arr:
            beginRow = group[0]
            endRow = group[1]
            event_name = ''
            field_explain_list = []
            filed_name_list = []
            field_type_list = []
            for rowId in range(beginRow, endRow + 1):
                row_data = self.df.iloc[rowId]
                if rowId == beginRow:
                    event_name = row_data[self.HEAD_EVENT_NAME]
                    self._eventNameArr.append(event_name)
                field_type = row_data[self.HEAD_FIELD_TYPE]
                field_name = row_data[self.HEAD_FIELD_TAG]
                field_explain = row_data[self.HEAD_FIELD_EXPLAIN]
                if pd.isna(field_type):
                    continue
                field_type_list.append(field_type) 
                filed_name_list.append(field_name)
                field_explain_list.append(field_explain)

            try:
                param_str_list = self._paramsCoder.GenerateSingleParmsClass(event_name, field_type_list, filed_name_list, field_explain_list)
                for str in param_str_list:
                    self._paramsArr.append(str)
            except Exception as e:
                print(f"[生成参数结构类] 处理事件名为{event_name}的合并单元格时，捕获到异常{e}")
                exception_trace = traceback.format_exc()
                print(exception_trace)

   

# 程序入口
if __name__ == "__main__":
    script_dir = os.path.dirname(os.path.abspath(__file__))
    os.chdir(script_dir)
    
    if len(sys.argv) != 2:
        print("ERROR: 运行脚本时必须携带(有且仅有)一个参数 => 版本号")
        sys.exit(1)

    version = sys.argv[1]
    print("[START] Analytics generate begin version => " + version)
    coder = AnalyticsCoder()
    coder.SOURCE_FILE_NAME = coder.SOURCE_FILE_NAME.replace("VersionHolder", version)
    coder.SOURCE_FILE_NAME = os.path.abspath(coder.SOURCE_FILE_NAME)

    if not os.path.exists(coder.SOURCE_FILE_NAME):
        print(f"ERROR: 运行脚本时指定版本的({version})的打点表格或路径不存在! \nPATH: {coder.SOURCE_FILE_NAME}")
        sys.exit(1)

    # print(f"### 打点表格文件存在性校验通过! \nPATH: {coder.SOURCE_FILE_NAME}")
    
    coder.PerformGenerateProcess(version)
    print('[END] Analytics generate scripts success !!!')